package com.ruoyi.flow.common.tools.filewatch;

import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.*;
import java.util.stream.Stream;

public class FileWatcher {
    /**
     * 监视的文件目录
     */
    private Path watchDirectory;
    /**
     * 监视的文件类型正则表达式
     */
    private FilenameFilter filenameFilter;
    /**
     * 监视到的文件监听器
     */
    private FileListener fileListener;

    public FileWatcher(Path watchDirectory, FilenameFilter filenameFilter, FileListener fileListener) {
        this.watchDirectory = watchDirectory;
        this.filenameFilter = filenameFilter;
        this.fileListener = fileListener;
    }

    public FileWatcher(Path watchDirectory, FileListener fileListener) {
        this(watchDirectory, null, fileListener);
    }

    /**
     * 由于监听文件目录并不会处理已经存在与目录中的历史文件，所以需要单独处理
     */
    private void executeHistoryFiles() {
        try {
            Stream<Path> stream = Files.list(this.watchDirectory);
            if (this.filenameFilter != null) {
                stream = stream.filter(path -> {
                    String fileName = path.getFileName().toString();
                    return filenameFilter.accept(this.watchDirectory.toFile(), fileName);
                });
            }
            stream.forEach(path -> {
                this.fileListener.onCreate(path);
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 监听目录，根据文件的变化处理文件
     */
    public void watch() {
        // 先处理历史文件
        executeHistoryFiles();
        // 监听新文件
        try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
            this.watchDirectory.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
            while (true) {
                WatchKey watchKey = watchService.take();
                for (WatchEvent event : watchKey.pollEvents()) {
                    WatchEvent.Kind eventKind = event.kind();
                    if (eventKind == StandardWatchEventKinds.OVERFLOW) {
                        continue;
                    }
                    String fileName = event.context().toString();
                    //文件名不匹配
                    if (this.filenameFilter != null && !this.filenameFilter.accept(this.watchDirectory.toFile(), fileName)) {
                        continue;
                    }
                    Path file = Paths.get(this.watchDirectory.toString(), fileName);
                    if (eventKind == StandardWatchEventKinds.ENTRY_CREATE) {
                        this.fileListener.onCreate(file);
                    } else if (eventKind == StandardWatchEventKinds.ENTRY_MODIFY) {
                        this.fileListener.onModify(file);
                    } else if (eventKind == StandardWatchEventKinds.ENTRY_DELETE) {
                        this.fileListener.onDelete(file);
                    }
                }
                boolean isKeyValid = watchKey.reset();
                if (!isKeyValid) {
                    break;
                }
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

}
